#!/usr/bin/env python

from gdata.service import GDataService

class portfolio_transactions():
  def __init__(self):
    self.bought = 0.0
    self.sold = 0.0
    self.transactions = {}

  def add_transaction(self, companyTicker, companyName, date="0000-00-00", pricePerShare="0.0", numShares="0.0", transaction="Buy", commission="0.0"):
    newEl = {"companyName":companyName, "date":date, "pricePerShare":pricePerShare, "numShares":numShares, 
      "commission":commission, "transaction":transaction}
    try:  
      self.transactions[companyTicker].append(newEl)
    except KeyError:
      #a list that begins with one element
      temp = [newEl] 
      self.transactions[companyTicker] = temp
    #balance reflects total bought and sold - it does not reflect current market value
    if transaction == "Buy":
      self.bought += float(pricePerShare) * float(numShares)
    elif transaction == "Sell":
      self.sold += float(pricePerShare) * float(numShares)

  def sort_transactions(self):
    self.stock_list = []
    for i in self.transactions.keys():
      self.stock_list.append(i)
    self.stock_list.sort()


class portfolio_performance():
  def __init__(self):
    self.stocks = {}
    
  def add_stock(self, symbol, fullname="", lastprice=None, daychange=None, shares=None, costBasis=None, mktval=None,
                gain=None, gainpercent=None, totgainpercent=None, daygain=None):
    self.stocks[symbol] = {"companyName":fullname, "lastprice":lastprice, "daychange":daychange, "shares":shares, "costBasis":costBasis,
                           "mktval":mktval, "gain":gain, "totgainpercent":totgainpercent, "gainpercent":gainpercent, "daygain":daygain}
  def sort_stocks(self):
    self.stock_list = []
    for i in self.stocks.keys():
      self.stock_list.append(i)
    self.stock_list.sort()

class portfolio():
  def __init__(self, username, password, portfolionumber=1):
    client = GDataService()
    client.email = username
    client.password = password
    client.service = "finance"
    client.ProgrammaticLogin()
    self.baseURL = "http://finance.google.com/finance/feeds/%(email)s/" % {'email':client.email}
    self.portfolionumber = portfolionumber
    positionsFeed = client.GetFeed(self.baseURL + "portfolios/" + str(self.portfolionumber) + "/positions?returns=true&transactions=true&positions=true")

    self.portfolio_transactions = portfolio_transactions()
    self.portfolio_performance = portfolio_performance()
  
    for entry in positionsFeed.entry:
      details = entry.FindExtensions("symbol")[0]
      symbol = details.attributes["symbol"]
      fullname = details.attributes["fullName"]

      data = entry.FindExtensions("positionData")[0]
      totgainpercent = float(data.attributes["returnOverall"])
      gainPercent = float(data.attributes["gainPercentage"])
      shares =float(data.attributes["shares"])

      #no need to process if you don't have any shares
      #if float(shares == 0):
      #  continue
      try:
        daygain = float(entry.FindExtensions("positionData")[0].FindChildren("daysGain")[0].FindChildren("money")[0].attributes["amount"])
      except IndexError:
        #index has no transactions
        continue
      costBasis = float(entry.FindExtensions("positionData")[0].FindChildren("costBasis")[0].FindChildren("money")[0].attributes["amount"])
      marketval = float(entry.FindExtensions("positionData")[0].FindChildren("marketValue")[0].FindChildren("money")[0].attributes["amount"])
      gain = float(entry.FindExtensions("positionData")[0].FindChildren("gain")[0].FindChildren("money")[0].attributes["amount"])
      if shares != 0:
        lastprice = marketval / float(shares)
      else:
        lastprice = 0

      daychange = daygain * lastprice + lastprice

      self.portfolio_performance.add_stock(symbol, fullname, lastprice=lastprice, daychange=daychange, shares=shares, costBasis=costBasis,
                                          mktval=marketval, gain=gain, totgainpercent=totgainpercent, gainpercent=gainPercent, daygain=daygain )

      transactions = entry.FindExtensions("feedLink")[0].FindChildren("feed")[0].FindChildren("entry")
      #for every company in the portfolio
      for transaction_co in transactions:
        thisTrans = transaction_co.FindChildren("transactionData")
        for transaction in thisTrans:
          try:
            date = transaction.attributes["date"]
            numShares = transaction.attributes["shares"]
            buysell = transaction.attributes["type"]
          except KeyError:
            #if an actual tranasction occured, the above should be there
            continue
          tcommission = transaction.FindChildren("commission")[0].FindChildren("money")[0].attributes["amount"]
          pricePerShare = transaction.FindChildren("price")[0].FindChildren("money")[0].attributes["amount"]
          self.portfolio_transactions.add_transaction(symbol, fullname, date, pricePerShare, numShares, buysell, tcommission)
  #  sort everything

  #this is used when only updating performance, but nothing else (eg transactions)
  #def update_performance(self):
  #  performanceFeed = client.GetFeed(self.baseURL + "portfolios/" + str(self.portfolionumber) + "/positions?returns=true&positions=true")

#class html_portfolio(portfolio)
#class qt_portfolio(portfolio

